﻿#pragma once

#include <xy/utils/coroutine.h>

namespace xy
{

namespace alg
{

template <typename T> struct iterable
{
    using return_type = utils::promise_generator<T>;

    /**
     * @brief 迭代器生成器
     *
     * @tparam Preserve 是否保留前一步迭代结果
     * @return std::function<return_type(std::size_t)>
     */
    template <bool Preserve = false> std::function<return_type(std::size_t)> generate()
    {
        return [this](std::size_t n) -> return_type {
            init();
            while (should_continue() && n-- > 0)
            {
                if constexpr (Preserve)
                    co_yield next_preserve();
                else
                    co_yield next();
            }
            finish();
        };
    }

  protected:
    virtual T next() = 0;

    // 初始化接口
    virtual void init()
    {
    }

    // 结束接口
    virtual void finish()
    {
    }

    // 迭代并保留之前的值
    virtual T next_preserve()
    {
        return T{};
    }

    // 用于终止条件
    virtual bool should_continue()
    {
        return true;
    }
};

} // namespace alg

} // namespace xy